package com.rc.web.service.impl;

import com.mybatisflex.core.paginate.Page;
import com.mybatisflex.spring.service.impl.ServiceImpl;
import com.rc.pojo.dto.question.QuestionAddDTO;
import com.rc.pojo.dto.question.QuestionDTO;
import com.rc.pojo.dto.question.QuestionQuery;
import com.rc.pojo.po.Question;
import com.rc.pojo.po.QuestionOption;
import com.rc.pojo.vo.question.QuestionListVO;
import com.rc.pojo.vo.question.QuestionOptionVO;
import com.rc.pojo.vo.question.QuestionPageVO;
import com.rc.pojo.vo.question.QuestionVO;
import com.rc.web.converter.QuestionConverter;
import com.rc.web.converter.QuestionOptionConverter;
import com.rc.web.mapper.QuestionMapper;
import com.rc.web.service.QuestionOptionService;
import com.rc.web.service.QuestionService;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.Comparator;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.stream.Collectors;

/**
 * 问题服务实现类
 * 提供问题相关的业务逻辑实现
 */
@Service
@RequiredArgsConstructor
public class QuestionServiceImpl extends ServiceImpl<QuestionMapper, Question> implements QuestionService {
    // 问题选项服务
    private final QuestionOptionService optionService;
    // 问题选项转换器
    private final QuestionOptionConverter optionConverter;
    // 问题转换器
    private final QuestionConverter questionConverter;

    /**
     * 根据植物ID和病虫害ID获取问题列表
     * @param plantId 植物ID
     * @param illId 病虫害ID
     * @return 问题列表VO
     */
    @Override
    public QuestionListVO getListByPlantId(Long plantId, Long illId) {
        // 获取该植物的所有问题
        List<Question> questionList = mapper.selectByPlantId(plantId, illId);
        QuestionListVO test = test(questionList);
        test.setPlantId(plantId);
        test.setIllId(illId);
        return test;
    }

    /**
     * 添加问题（包含选项）
     * @param dto 问题添加DTO
     */
    @Override
    @Transactional
    public void add(QuestionAddDTO dto) {
        Long plantId = dto.getPlantId();
        Long illId = dto.getIllId();
        // 删除原有问题和选项
        mapper.deleteByPlantId(plantId, illId);
        optionService.deleteByPlantId(plantId, illId);

        List<QuestionDTO> questionDTOList = dto.getQuestions();

        // 保存所有问题
        List<Question> questionList = questionDTOList.stream()
                .map(item -> Question.builder()
                        .content(item.getContent())
                        .plantId(plantId)
                        .illId(illId)
                        .queIndex(item.getIndex())
                        .type(item.getType())
                        .build())
                .sorted(Comparator.comparing(Question::getQueIndex))
                .toList();

        this.saveBatch(questionList);

        // 创建问题索引映射
        Map<Integer, Question> indexQuestionMap = questionList.stream()
                .collect(Collectors.toMap(Question::getQueIndex, item -> item));

        // 保存所有选项
        List<QuestionOption> optionList = questionDTOList.stream()
                .flatMap(questionDTO ->{
                    Integer index = questionDTO.getIndex();
                    Question question = indexQuestionMap.get(index);

                    return questionDTO.getOptions().stream()
                            .map(optionDTO -> {
                                QuestionOption option = optionConverter.AddDTO2PO(optionDTO);
                                option.setPlantId(plantId);
                                option.setIllId(illId);
                                option.setQuestionId(question.getId());

                                // 设置下一个问题ID
                                Integer nextQuestionIndex = optionDTO.getNextQuestionIndex();
                                Optional<Question> nextQuestion = Optional.ofNullable(indexQuestionMap.get(nextQuestionIndex));
                                nextQuestion.ifPresent(q -> option.setNextQuestionId(q.getId()));
                                return option;
                            });
                })
                .toList();

        optionService.saveBatch(optionList);
    }

    /**
     * 分页查询问题
     * @param query 查询条件
     * @return 分页结果
     */
    @Override
    public Page<QuestionPageVO> getPage(QuestionQuery query) {
        return mapper.selectPage(query);
    }

    /**
     * 根据ID删除问题
     * @param id 问题ID
     */
    @Override
    public void deleteOneById(Long id) {
        this.removeById(id);
        optionService.deleteByQuestionId(id);
    }

    /**
     * 根据ID获取问题详情
     * @param id 问题ID
     * @return 问题VO
     */
    @Override
    public QuestionVO getOneById(Long id) {
        Question question = this.getById(id);
        QuestionVO vo = questionConverter.toVO(question);

        // 获取问题选项
        List<QuestionOptionVO> options = optionService.getByQuestionId(List.of(id))
                .stream()
                .map(optionConverter::toVO)
                .toList();

        vo.setOptions(options);
        return vo;
    }

    /**
     * 根据病虫害ID获取问题列表
     * @param illId 病虫害ID
     * @return 问题列表VO
     */
    @Override
    public QuestionListVO getListByIllId(Long illId) {
        List<Question> questionList = mapper.selectByIllId(illId);
        QuestionListVO test = test(questionList);
        test.setPlantId(illId);
        return test;
    }

    /**
     * 内部方法：组装问题列表VO
     * @param questionList 问题列表
     * @return 问题列表VO
     */
   private QuestionListVO test(List<Question> questionList) {
       // 获取问题的所有选项
       List<Long> questionIdList = questionList.stream().map(Question::getId).toList();
       List<QuestionOption> optionList = optionService.getByQuestionId(questionIdList);

       // 根据问题ID分组选项
       Map<Long, List<QuestionOption>> questionOptionMap = optionList.stream()
               .collect(Collectors.groupingBy(QuestionOption::getQuestionId));

       // 组装VO
       List<QuestionVO> questions = questionList.stream()
               .sorted(Comparator.comparing(Question::getQueIndex))
               .map(item -> {
                   QuestionVO vo = questionConverter.toVO(item);

                   // 组装选项VO
                   List<QuestionOption> questionOptions = questionOptionMap.getOrDefault(item.getId(), List.of());
                   List<QuestionOptionVO> optionVOList = questionOptions
                           .stream()
                           .map(optionConverter::toVO)
                           .toList();

                   // 设置选项的下一个问题索引
                   optionVOList.forEach(optionVO ->
                           questionList.forEach(question -> {
                               if (question.getId().equals(optionVO.getNextQuestionId())) {
                                   optionVO.setNextQuestionIndex(questionList.indexOf(question));
                               }
                           })
                   );

                   vo.setOptions(optionVOList);
                   return vo;
               }).toList();

       return QuestionListVO.builder()
               .questions(questions)
               .build();
   }
}
